﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntitiesLayer;
using System.IO;
using DataLayer;
using Bitacora;

namespace BusinessLayer
{
    public static class BatchImporterProcesses
    {
        public static bool toProcess = true;

        //Metodo usado para subir los registros de cheques desde los archivos planos hacia la base de datos
        static public void CargarDataBaseDatos()
        {
            foreach (String fechaContable in System.IO.Directory.GetDirectories(Configuracion.rutaArchivosData))
             {
                 Services.EnviarLog("Unisys Batch Importer To DB", 103, "Entrando en el directorio: " + fechaContable, "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                    foreach (String runDirectory in System.IO.Directory.GetDirectories(fechaContable)) 
                    {
                        DirectoryInfo directorioCorrida = new DirectoryInfo(runDirectory);
                        Services.EnviarLog("Unisys Batch Importer To DB", 103, "Entrando en el directorio: " + directorioCorrida.Name, "CargarDataBaseDatos", Bitacora.TipoError.Informacion);

                        if (directorioCorrida.GetFiles("CIERRE.txt").Any())
                        {
                            FileInfo fileC = directorioCorrida.GetFiles("CIERRE.txt").ElementAt(0);
                            fileC.Delete();
                        }

                        foreach (FileInfo archivo in directorioCorrida.GetFiles("*.txt"))//se buscan archivos dentro de la carpeta de la categoria
                        {
                            StreamReader archivoBatch = null;
                            try
                            {
                                

                                if (CorrectTime() && toProcess)
                                {
                                    string camaraCheque = archivo.Name.Substring(0, 4);
                                    List<string> lineasNoCargadas = new List<string>();
                                    int numeroChequesCargados = 0;
                                    archivoBatch = archivo.OpenText();
                                    string datosCheque = "";
                                    bool primeraLinea = true;
                                    int indiceCheques = 0;

                                    //Separar datos de cheque y subirlos a la base de datos
                                    string[] listaDatosCheque;
                                    Services.EnviarLog("Unisys Batch Importer To DB", 515, "Se inicia la lectura de registros de cheques desde archivo '" + archivo.Name + "'.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);

                                    while (!String.IsNullOrEmpty(datosCheque = archivoBatch.ReadLine()))
                                    {
                                        //si es la primera linea seguir con la siguiente
                                        if (primeraLinea)
                                        {
                                            primeraLinea = false;
                                            continue;
                                        }

                                        listaDatosCheque = datosCheque.Split(',');
                                        Services.EnviarLog("Unisys Batch Importer To DB", 518, "Realizando la carga del registro: " + datosCheque + "...", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                        //Cheque que se utilizará para subir a la base de datos
                                        Cheque chequeFinal = ObtenerDataCheque(camaraCheque, listaDatosCheque, directorioCorrida.Name, archivo.Name, indiceCheques,archivo.Directory.Parent.Name); //metodo para validar tipo de cheque y saber que es cada valor

                                        if (chequeFinal == null)
                                        {
                                            //No se encontró camara para la linea leída.
                                            Services.EnviarLog("Unisys Batch Importer To DB", 516, "El registro: '" + datosCheque + "' no pertenece a ninguna de las cámaras.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                            continue;
                                        }


                                        //Revisar si existe el cheque a insertar en la base de datos INFOIMG
                                        if (SqlDataClass.SQLWorkItemExiste(Configuracion.campoFecha,Configuracion.campoDocumento, Configuracion.campoCliente))
                                        {
                                            //Ya existe el cheque en ATTRIBUTES
                                            Services.EnviarLog("Unisys Batch Importer To DB", 517, "El registro: '" + datosCheque + "' ya existe en InfoImage. Se omite la carga.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                            continue;
                                        }

                                        //Subir a la base de datos.
                                        
                                        int resultadoInsert = SqlDataClass.InsertarSql(chequeFinal);

                                        //si el resultado de la insercion es valida (1 registro) aumentar en 1
                                        if (resultadoInsert == 1)
                                        {
                                            numeroChequesCargados++;
                                            Services.EnviarLog("Unisys Batch Importer To DB", 259, "Se realizó correctamente la carga del registro: " + datosCheque, "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                        }
                                        else
                                        {
                                            //agregar datos de cheque a la lista de cheques no cargados a la base de datos
                                            Services.EnviarLog("Unisys Batch Importer To DB", 519, "NO se realizó la carga del registro: " + datosCheque, "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                            lineasNoCargadas.Add(datosCheque);
                                        }
                                        indiceCheques++;

                                    }

                                    //Cerrar archivo leido
                                    archivoBatch.Close();
                                    Services.EnviarLog("Unisys Batch Importer To DB", 107, "Archivo '" + archivo.Name + "'cerrado correctamente", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);

                                    //Mover el archivo data al realizar la insercion de los cheques en la base de datos hacia la ruta especificada en chargedPath
                                
                               
                                    if (lineasNoCargadas.Count == 0)
                                    {
                                        Services.EnviarLog("Unisys Batch Importer To DB", 261, "Se insertaron todos los registros del archivo '" + archivo.Name + "'. Cantidad de registros cargados correctamente: '" + numeroChequesCargados + "'.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                        if (!Directory.Exists(Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name))
                                            Directory.CreateDirectory(Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name);
                                        
                                        //Si existe el archivo a cargado se borra
                                        if (File.Exists(Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name))
                                            File.Delete(Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name);

                                        archivo.MoveTo(Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name);
                                        Services.EnviarLog("Unisys Batch Importer To DB", 104, "Archivo '" + archivo.Name + "' movido hacia: '" + Configuracion.rutaArchivosCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name + "'.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                    }
                                    else
                                    {
                                        //Mostrar registros que no se insertaron
                                        Services.EnviarLog("Unisys Batch Importer To DB", 520, "Del archivo '" + archivo.Name + "' no se insertaron los siguientes registros:\n", "CargarDataBaseDatos", Bitacora.TipoError.Log);
                                        foreach (string lineC in lineasNoCargadas)
                                        {
                                            Services.EnviarLog("Unisys Batch Importer To DB", 520, "     " + lineC + "\n","CargarDataBaseDatos",Bitacora.TipoError.Log);
                                        }
                                        
                                        //Guardar el archivo no movido
                                        if (!Directory.Exists(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name))
                                            Directory.CreateDirectory(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name);

                                        FilesManagement.GuardarData(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name + "noCharged", false, lineasNoCargadas);
                                        Services.EnviarLog("Unisys Batch Importer To DB", 105, "Archivo con registros NO cargados guardado en : '" + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name + "noCharged" + "'.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                        
                                        //mover el archivo a la carpeta de datos no cargados a la base datos
                                        if (File.Exists(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name))
                                            File.Delete(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name);

                                        archivo.MoveTo(Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name);
                                        Services.EnviarLog("Unisys Batch Importer To DB", 106, "Archivo '" + archivo.Name + "' movido hacia: '" + Configuracion.rutaArchivosNoCargados + "\\" + directorioCorrida.Parent.Name + "\\" + directorioCorrida.Name + "\\" + archivo.Name + "'.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                    }
                


                                }
                                else
                                {
                                    Services.EnviarLog("Unisys Batch Importer To DB", 260, "Se acabo el tiempo de ejecución del servicio", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                    return;
                                }
                            }
                            catch (Exception exc)
                            {
                                Services.EnviarLog("Unisys Batch Importer To DB", 108, "Se presentó el siguiente inconveniente al procesar el archivo '" + archivo.Name + "': " + exc.Message + ". Se mueve el archivo hacia: '" + Configuracion.rutaArchivosNoCargados + "\\" + archivo.Name + "'.\n Se continuá con el siguiente archivo.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                                archivoBatch.Close();

                                if (File.Exists(Configuracion.rutaArchivosNoCargados + "\\" + archivo.Name))
                                    File.Delete(Configuracion.rutaArchivosNoCargados + "\\" + archivo.Name);
                                archivo.MoveTo(Configuracion.rutaArchivosNoCargados + "\\" + archivo.Name);
                            }


                        }


                       

                        //Borrar el directorio que contiene los datafiles si este se queda vacio
                        if (!directorioCorrida.GetFiles().Any())
                        {
                            directorioCorrida.Delete();
                            Services.EnviarLog("Unisys Batch Importer To DB", 109, "Directorio '" + directorioCorrida.FullName + "' borrado.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                        }


                    }

                    //Borrar el directorio que contiene los directorios run si este se queda vacio
                    if (!Directory.GetDirectories(fechaContable).Any())
                    {

                        Directory.Delete(fechaContable);
                        Services.EnviarLog("Unisys Batch Importer To DB", 109, "Directorio '" + fechaContable + "' borrado.", "CargarDataBaseDatos", Bitacora.TipoError.Informacion);
                    }

             }


            //Reintentos
            ProcesarDocumentosRestantes();


        }

        //Obtiene los valores de cada cheque segun la configuracion de la camara correspondiente
        private static Cheque ObtenerDataCheque(string numeroCamaraCheque, string[] dataCheque, string codigoCorrida, string nombreArchivo, int indiceCheque, string nombreDirectorioFecha)
        {
            Cheque chequeFinal = new Cheque();
            Camara camaraCheque = null;

            //Establecer la camara que se usara para obtener los datos.
            camaraCheque = (Camara)BatchImporter_Fields.ClonacionAnidada<Camara>(Configuracion.parametrizacionCampos.BuscarCamara(numeroCamaraCheque, dataCheque.Length));

            if (camaraCheque == null)
            {
                return null;
            }


            //Obtener y Establecer los valores del cheque 
            string codigoImagen = "";
            for (int ind = 0; ind < camaraCheque.camposValidos.Count; ind++)
            {
                string valorP = camaraCheque.camposValidos[ind].posicion.ToString();
                if (valorP.Length >= 4)
                {
                    switch (valorP.Substring(0, 4))
                    {
                        case "1000"://fecha
                            {
                                camaraCheque.camposValidos[ind].valor = 
                                    nombreDirectorioFecha.Substring(6, 2) + "-" + nombreDirectorioFecha.Substring(4, 2) + "-" + nombreDirectorioFecha.Substring(0, 4);
                                break;
                            }
                        case "1001": //valor estatico
                            {
                                camaraCheque.camposValidos[ind].valor =
                            camaraCheque.camposValidos[ind].posicion.ToString().Remove(0, 4);//, checkCamera.camposValidos[ind].position.ToString().Length - 4);
                                break;
                            }
                        case "1002": //establecer mov_tarea desde descripcion
                            {
                                camaraCheque.camposValidos[ind].valor = camaraCheque.movTarea;
                                break;
                            }
                        case "1003": //tomar una cantidad especifica de caracteres de una posicion
                                    //1003pos1003ini1003cant
                            {
                                valorP = valorP.Remove(0, 4);
                                valorP = valorP.Replace("1003",";");
                                string[] espCaract = valorP.Split(';');
                                camaraCheque.camposValidos[ind].valor = 
                                    dataCheque[Int32.Parse(espCaract[0])].Substring(Int32.Parse(espCaract[1]),Int32.Parse(espCaract[2]));
                                break;
                            }
                        case "1004": //tomar una cantidad especifica de caracteres desde la derecha del texto
                            //1004pos1004numCaract
                            {
                                valorP = valorP.Remove(0, 4);
                                valorP = valorP.Replace("1004", ";");
                                string[] espCaract = valorP.Split(';');
                                camaraCheque.camposValidos[ind].valor =
                                    dataCheque[Int32.Parse(espCaract[0])].Substring(dataCheque[Int32.Parse(espCaract[0])].Length - Int32.Parse(espCaract[1]), Int32.Parse(espCaract[1]));
                                break;
                            }
                        case "1005": //tomar una cantidad especifica de caracteres desde la izquierda del texto
                            //1005pos1005numCaract
                            {
                                valorP = valorP.Remove(0, 4);
                                valorP = valorP.Replace("1005", ";");
                                string[] espCaract = valorP.Split(';');
                                camaraCheque.camposValidos[ind].valor =
                                    dataCheque[Int32.Parse(espCaract[0])].Remove(0,Int32.Parse(espCaract[1]));
                                break;
                            }
                    }


                }
                else
                {
                    camaraCheque.camposValidos[ind].valor = dataCheque[Int32.Parse(camaraCheque.camposValidos[ind].posicion.ToString())];
                }
                
                //Revisar si es el campo de imagen
                if ((camaraCheque.camposValidos[ind].nombreBaseDatos.Equals("imageCode")) &&
                                                (camaraCheque.camposValidos[ind].nombreIIF.Equals("imageCode")))//Campo codigo imagen
                {
                    codigoImagen = camaraCheque.camposValidos[ind].valor;
                }
                

            }

            //Asignar los datos al cheque
            chequeFinal.camara = camaraCheque;
            chequeFinal.camara.codigoCheque = numeroCamaraCheque;

            chequeFinal.direccionData = Configuracion.rutaArchivosCargados + "\\" + nombreDirectorioFecha + "\\" + codigoCorrida + "\\" + nombreArchivo;
            chequeFinal.imagenAnversa = Configuracion.rutaImagenes + "\\" + nombreDirectorioFecha + "\\" + codigoCorrida + "\\" + codigoImagen + "FJ.JPG";
            chequeFinal.imagenReversa = Configuracion.rutaImagenes + "\\" + nombreDirectorioFecha + "\\" + codigoCorrida + "\\" + codigoImagen + "RJ.JPG";

            //Asignación del estado del cheque
            if (NoNocesitaImagen(camaraCheque.ObtenerCampo(Configuracion.campoCategoria).valor))//No requiere imagenes
            {
                chequeFinal.imagenAnversa = "";
                chequeFinal.imagenReversa  = "";
                chequeFinal.estado = 5;
                Services.EnviarLog("Unisys Batch Importer To DB", 110, "Este registro no requiere imagénes.", "ObtenerDataCheque", Bitacora.TipoError.Informacion);
            }
            else if (!File.Exists(chequeFinal.imagenAnversa) || !File.Exists(chequeFinal.imagenReversa)) //No existen las imagenes
            {
                chequeFinal.estado = 2;
                Services.EnviarLog("Unisys Batch Importer To DB", 111, "No existen las dos imágenes requeridas por este registro.", "ObtenerDataCheque", Bitacora.TipoError.Informacion);
            }
            else//Si existen las imagenes
            {
                chequeFinal.estado = 1;
                Services.EnviarLog("Unisys Batch Importer To DB", 112, "Si existen las imágenes requeridas por este registro.", "ObtenerDataCheque", Bitacora.TipoError.Informacion);
            }

            


            return chequeFinal;
        }

        //Revisa que la hora de ejecucion sea la correcta
        private static bool CorrectTime()
        {
            int horaInicio = Int32.Parse(Configuracion.horarioEjecucion[1]);
            int horaFin = Int32.Parse(Configuracion.horarioEjecucion[2]);


            int horaActual = Int32.Parse(DateTime.Now.ToString("HHmm")); 

            if ((horaInicio < horaActual) && (horaActual < horaFin))
            {
                return true;
            }
            else
            {
                return false;
            }


        }

        private static bool NoNocesitaImagen(string categoria)
        {
            foreach (string cat in Configuracion.CategoriasSinImagenes)
            {
                if (categoria.Equals(cat))
                    return true;
            }
            return false;
        }


        private static void ProcesarDocumentosRestantes()
        {
            for (int i = 0; i < Configuracion.numeroReintentos; i++)
            {
                List<Cheque> chequesList = SqlDataClass.LeerChequesRestantes();
                if (chequesList != null)
                {
                    Services.EnviarLog("Unisys Batch Importer To DB", 521, "Reitentando existencia de imágenes...", "ProcesarDocumentosRestantes", Bitacora.TipoError.Informacion);
                    foreach (Cheque cheque in chequesList)
                    {
                        if (File.Exists(cheque.imagenAnversa) && File.Exists(cheque.imagenReversa)) //Si existen las imagenes
                        {
                            SqlDataClass.ActualizarEstado(cheque.IDCheque.ToString(), 1);
                            Services.EnviarLog("Unisys Batch Importer To DB", 113, "Se encontraron las imágenes para el registro: '" + cheque.IDCheque + "'. Se cambió el estado a 1.", "ProcesarDocumentosRestantes", Bitacora.TipoError.Informacion);
                        }
                    }
                }
            }
        }



    }
}
